use std::collections::HashMap;

use serde::Deserialize;
#[cfg(feature = "Casbin")]
mod casbin;
mod cors;
mod db;
mod logger;
mod loginmanager;
mod redis;
#[cfg(feature = "jinjia")]
mod template;
mod web;

#[derive(Debug, Default, Clone, Deserialize)]
pub struct Config {
    pub author: Option<String>,
    #[serde(default)]
    pub database: db::DbConfig,
    #[serde(default)]
    pub web: web::WebConfig,
    #[cfg_attr(feature = "jinjia", serde(default))]
    #[cfg(feature = "jinjia")]
    pub template: template::TemplateConfig,
    #[serde(default)]
    pub logger: logger::LoggerConfig,
    #[cfg(feature = "Casbin")]
    pub casbin: Option<casbin::CasbinConfig>,
    #[serde(default)]
    pub redis: Option<redis::RedisConfig>,
    #[serde(default)]
    pub loginmanager: loginmanager::LoginmanagerConfig,
    #[serde(flatten)]
    pub ext: HashMap<String, serde_json::Value>,
}

impl Config {
    /// load config from path
    /// return None if config file not exists
    pub fn from_file<P: AsRef<std::path::Path>>(path: P) -> Option<Self> {
        match std::fs::read_to_string(path) {
            Ok(s) => Some(serde_yaml::from_str(s.as_str()).unwrap()),
            _ => None,
        }
    }

    /// load config from file `application.yml`
    pub fn default() -> Self {
        match Self::from_file("application.yml") {
            Some(s) => s,
            None => {
                println!("fail to load application.yml, start with default config");
                Default::default()
            }
        }
    }
}
